package com.acme.bankapp.domain.bank.client;


/**
 * @author Andrey Alekov
 *
 */
import java.io.Serializable;
import java.util.ArrayList;

import javax.security.auth.login.AccountNotFoundException;

import com.acme.bankapp.account.AbstractAccount;

/**
 * Bank client class.
 */
public class Client implements Serializable{
	private static final long serialVersionUID = 848250435792460016L;
	private String name;
	private Gender gender;
	private ArrayList<AbstractAccount> accounts;
	
	/**
	 * Constructor
	 * @param clientName to set client name
	 * @param clientGender to set client gender.
	 */
	public Client(String clientName, Gender clientGender) {
		this.setGender(clientGender);
		this.setName(clientName);
		this.accounts =  new ArrayList<AbstractAccount>();
	}
	
	/**
	 * (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) { return true;}
		if (obj == null) { return false;}
		if (obj instanceof Client){
			final Client clientObj = (Client) obj;
			if (!this.name.equals(clientObj.getName())){ return false; }
			if (!this.gender.equals(clientObj.getGender())){ return false; }
			// not need to verify accounts for client.
			return true;
		}
		return false;
	}
	
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((accounts == null) ? 0 : accounts.hashCode());
		result = prime * result + ((gender == null) ? 0 : gender.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	
	/**
	 * Return all accounts for client
	 * @return ArrayList<AbstractAccount> list of accounts for client
	 */
	public ArrayList<AbstractAccount> getAccounts(){
		return this.accounts;
	}
	
	/**
	 * Get client salutation string.
	 * @return string of salutation
	 */
	public String getClientSalutation() {
		return this.gender.getGreetings();
	}
	
	/**
	 * Get client name
	 * @return string client name
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * Set client name
	 * @param name of client
	 */
	public void setName(String name) {
		this.name = name;
	}
	
	/**
	 * Get client gender.
	 * @return gender of client
	 */
	public Gender getGender() {
		return gender;
	}
	
	/**
	 * Set client gender
	 * @param gender to set
	 */
	public void setGender(Gender gender) {
		this.gender = gender;
	}
	
	/**
	 * Return specific account by accountId
	 * @param accountId client account identifier
	 * @return account client account
	 * @throws AccountNotFoundException if account not found
	 */
	public AbstractAccount getAccount(Long accountId) 
			throws AccountNotFoundException {
		for (AbstractAccount account : this.accounts) {
			if (account.getAccountId() == accountId){
				return account;
			}
		}
		throw new AccountNotFoundException("Client account " + accountId 
				+ " not found.");
	}
	
	/**
	 * Add new account to client
	 * @param account to add
	 */
	public void addAccount(AbstractAccount account) {
		this.accounts.add(account);
	}
	
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Client: " + getClientSalutation() + " " + this.name;
	}
}
